﻿using CPAIS.Model;
using CPAIS.Updater;
using System;
using System.Xml;

namespace CPAIS.LogParser.PluginsWithXmlReader
{
    /// <summary>
    /// Log parser for parsing event log file with XML Root TAG 'EventLog', like:
    /// 
    /// <EventLog>
    ///     <Case CP_ID="4" Visit_ID="8" OutPatient_ID="100351" InPatient_ID="117470" Diagnosis_Date="2011-11-26T14:50:00.000" Admit_Date="2011-11-26T14:07:16.000" Discharge_Date="2011-11-30T15:00:00.000" BirthDay="1935-06-23T00:00:00.000" Sex="男" Department="心血管内科三病区" Cost="51402.22">
    ///         <Event Type="Observation" ID="1" DateTime="2011-11-26 14:50:00" isNPL="False" Data="76" Unit="Years" Description="年龄" />
    ///         <Event Type="Action" ID="7" DateTime="2011-11-30 08:00:00" isNPL="False" Data="0.1" Unit="g" Description="阿司匹林肠溶片(拜耳-GE) 口服" />
    ///     </Case>
    /// </EventLog>
    /// 
    /// </summary>
    public class LogParserB : ILogParserWithXmlReader
    {
        #region String used for parsing XML file
        private const string EventLog = "EventLog";
        private const string Case = "Case";
        private const string Visit_ID = "Visit_ID";
        private const string InPatient_ID = "InPatient_ID";
        private const string Admit_Date = "Admit_Date";
        private const string Discharge_Date = "Discharge_Date";
        private const string BirthDay = "BirthDay";
        private const string Sex = "Sex";
        private const string Department = "Department";
        private const string Cost = "Cost";
        private const string Event = "Event";
        private const string TypeL = "Type";
        private const string DateTimeL = "DateTime";
        private const string Description = "Description";

        private const string Male = "男";
        private const string Female = "女";
        private const string Observation = "Observation";
        private const string Action = "Action";
        #endregion

        public string XmlTag
        {
            get { return EventLog; }
        }

        public void Parse(LogModel logModel, XmlReader reader, StateUpdater updater)
        {
            while (reader.Read())
            {
                #region Depth 1
                if (reader.Depth < 1)
                    break;
                else if (reader.Depth == 1 && reader.NodeType == XmlNodeType.Element && reader.Name == Case)
                {
                    #region Read Patient Attributes

                    string
                        strVistID = "",
                        strInPatientID = "",
                        strSex = "",
                        strDepartment = "",
                        strCost = "";
                    DateTime
                        admitTime = new DateTime(),
                        dischargeTime = new DateTime(),
                        birthday = new DateTime();

                    while (reader.MoveToNextAttribute())
                    {
                        switch (reader.Name)
                        {
                            case InPatient_ID:
                                strInPatientID = reader.ReadContentAsString().Trim();
                                break;
                            case Visit_ID:
                                strVistID = reader.ReadContentAsString().Trim();
                                break;
                            case Sex:
                                strSex = reader.ReadContentAsString().Trim();
                                break;
                            case Department:
                                strDepartment = reader.ReadContentAsString().Trim();
                                break;
                            case Cost:
                                strCost = reader.ReadContentAsString().Trim();
                                break;
                            case Admit_Date:
                                admitTime = reader.ReadContentAsDateTime();
                                break;
                            case Discharge_Date:
                                dischargeTime = reader.ReadContentAsDateTime();
                                break;
                            case BirthDay:
                                birthday = reader.ReadContentAsDateTime();
                                break;
                        }
                    }
                    Trace trace = new Trace(logModel, strInPatientID + "_" + strVistID);
                    trace.Sex = strSex == Male ? SexType.Male : (strSex == Female ? SexType.Female : SexType.Unknown);
                    trace.Department = strDepartment;
                    trace.Cost = strCost == "" ? 0.0 : double.Parse(strCost);
                    trace.Admit = admitTime;
                    trace.Discharge = dischargeTime;
                    trace.Birthday = birthday;

                    #endregion

                    while (reader.Read())
                    {
                        #region Depth 2
                        if (reader.Depth < 2)
                            break;
                        else if (reader.Depth == 2 && reader.NodeType == XmlNodeType.Element && reader.Name == Event)
                        {
                            string
                                typeName = "",
                                description = "",
                                dateTime = "";
                            DateTime timestamp = new DateTime();

                            while (reader.MoveToNextAttribute())
                            {
                                switch (reader.Name)
                                {
                                    case TypeL:
                                        typeName = reader.ReadContentAsString().Trim();
                                        break;
                                    case DateTimeL:
                                        dateTime = reader.ReadContentAsString().Trim();
                                        break;
                                    case Description:
                                        description = reader.ReadContentAsString().Trim();
                                        break;
                                }
                            }

                            timestamp = DateTime.Parse(dateTime);
                            if (typeName == Observation)
                            {
                                ObservationEvent entry = new ObservationEvent(trace, timestamp, description);
                                trace.AddObservation(entry);
                            }
                            else if (typeName == Action)
                            {
                                ActionEvent entry = new ActionEvent(trace, timestamp, description);
                                trace.AddAction(entry);
                            }
                        }
                        #endregion
                    }
                    trace.OrderTrace();
                    logModel.AddTrace(trace);
                    if (updater != null)
                        updater.UpdateMessage(string.Format("{0} traces have been loaded...", logModel.TraceCount));
                }
                #endregion
            }
        }
    }
}
